package com.electronic.modules.verify;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cebpubservice.cashare.sdk.electronicsealsignatureandverifysignature.result.BatchGetCAOrgCertChainInfoResultDTO;
import com.electronic.constant.CommonConstant;
import com.electronic.domain.CebsSdkProperties;
import com.electronic.domain.EncryptionAlgorithmConstants;
import com.electronic.enums.AlgorithmEnum;
import com.electronic.enums.CertAlgEnum;
import com.electronic.enums.FileTypeEnum;
import com.electronic.enums.VerifySignatureStatusEnum;
import com.electronic.exception.ResultCode;
import com.electronic.exception.ServiceException;
import com.electronic.gbt.GBT6_1_1.SESeal;
import com.electronic.gbt.GBT6_1_2_1.SES_SealInfo;
import com.electronic.gbt.GBT6_1_2_2.SES_Header;
import com.electronic.gbt.GBT6_1_2_4.CertDigestList;
import com.electronic.gbt.GBT6_1_2_4.CertDigestObj;
import com.electronic.gbt.GBT6_1_2_4.CertInfoList;
import com.electronic.gbt.GBT6_1_2_4.SES_ESPropertyInfo;
import com.electronic.gbt.GBT6_1_2_5.SES_ESPictrueInfo;
import com.electronic.gbt.GBT6_1_2_6.ExtData;
import com.electronic.gbt.GBT6_1_2_6.ExtensionDatas;
import com.electronic.gbt.GBT7_1_1.SES_Signature;
import com.electronic.gbt.GBT7_1_2.TBS_Sign;
import com.electronic.modules.other.result.ComputerInfo;
import com.electronic.modules.verify.param.CommitVerifySignatureDTO;
import com.electronic.modules.verify.param.GetFileElectronicSealSignatureListDTO;
import com.electronic.modules.verify.param.GetSignatureInfoDTO;
import com.electronic.modules.verify.param.GetSignatureListInfoDTO;
import com.electronic.modules.verify.result.*;
import com.electronic.utils.*;
import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.source.RandomAccessFileOrArray;
import com.itextpdf.kernel.exceptions.PdfException;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.signatures.PdfPKCS7;
import com.itextpdf.signatures.SignatureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.Base64Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author zyh 
 * ================================
 * Date: 2024/8/2
 * Time: 上午10:09
 * ================================
 */
@Slf4j
public class VerifyService {
    /**
     * 判断文件是否存在及文件类型
     *
     * @param relativePath 文件地址
     * @return 文件类型
     */
    private static String checkIfPdfExists(String relativePath) {
        File file = new File(relativePath);
        // 判断文件是否存在
        if (file.exists()) {
            // 获取文件名
            String fileName = file.getName();
            // 检查文件扩展名是否为.pdf
            if (fileName.endsWith(".pdf")) {
                //验证PDF文件是否可用
                IFileUtil.verifyPdfUsable(relativePath);
                return FileTypeEnum.PDF.getType();
            } else if (fileName.endsWith(".ofd")) {
                return FileTypeEnum.OFD.getType();
            } else {
                throw new ServiceException(ResultCode.ERROR_FILE_EXT, "验章文件无效，只支持OFD或PDF文件");
            }
        } else {
            throw new ServiceException(ResultCode.ERROR_FILE_NOT_FOUND, "验章文件不存在");

        }
    }

    public static GetVerifyResultVO commitVerifySignature(CommitVerifySignatureDTO certificationSignatureDTO) {
        String filePath = certificationSignatureDTO.getPath();
        //验章文件类型 是否可用 返回文件类型
        String fileType = checkIfPdfExists(certificationSignatureDTO.getPath());
        File file = new File(filePath);
        String fileName = file.getName();
        //构造验章对象并持久化
        VerifySignature verifySignature = new VerifySignature();
        verifySignature.setFileName(fileName);
        verifySignature.setVerifyStatus(VerifySignatureStatusEnum.VERIFY_ING.getCode());
        verifySignature.setCreateTime(LocalDateTime.now());
        List<GetSignatureVO> signatureList = new ArrayList<>();
        //调用验章方法查询验章结果集合
        List<VerifySignatureResult> verifySignatureResultList = executeVerifySignature(verifySignature, fileType, filePath, certificationSignatureDTO.getCebsSdkProperties(), CertChainsUtil.readAndConvert(certificationSignatureDTO.getCertChainPath()));
        //key：签章者  value：验章信息
        Map<String, List<VerifySignatureResult>> signerSignatureMap = verifySignatureResultList.stream().collect(Collectors.groupingBy(VerifySignatureResult::getSigner));
        signerSignatureMap.forEach((key, value) -> {
            //循环获取签章者签署印章个数
            AtomicInteger times = new AtomicInteger(0);
            value.stream().forEach(t -> {
                times.addAndGet(Objects.isNull(t.getBatchSignTimes()) ? 1 : t.getBatchSignTimes());
            });

            GetSignatureVO getSignatureVO = GetSignatureVO.builder()
                    .signer(key)
                    .signCount(times.get())
                    .build();
            signatureList.add(getSignatureVO);
        });
        //如果VerifySignatureResult.getSignatureValidity()、VerifySignatureResult.getCertValidity()同时为true，则验章结果为true,否则验章结果为false;
        //从verifySignatureResultList中获取验章结果
        Map<String,Boolean> signatureDomainIdAndStatus = verifySignatureResultList.stream().collect(Collectors.toMap(VerifySignatureResult::getSignatureName, t -> t.getSignatureValidity() && t.getCertValidity()));
        Map<String,List> signatureDomainIdAndCertValidityRemark = verifySignatureResultList.stream().collect(Collectors.toMap(VerifySignatureResult::getSignatureName, t -> StrUtil.split(t.getCertValidityRemark(), ",")));
        //组装验章返回对象vo
        GetVerifyResultVO vo = GetVerifyResultVO.builder()
                .verifyResult(verifySignature.getVerifyResult())
                .verifyStatus(verifySignature.getVerifyStatus())
                .verifyResultRemark(StrUtil.split(verifySignature.getVerifyResultRemark(), ","))
                .signatureList(signatureList)
                .signatureDomainIdAndStatusMap(signatureDomainIdAndStatus)
                .signatureDomainIdAndCertValidityRemark(signatureDomainIdAndCertValidityRemark).build();

        return vo;
    }

    public static List<VerifySignatureResult> executeVerifySignature(VerifySignature verifySignature, String fileType, String path, CebsSdkProperties cebsSdkProperties, List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS) {
        List<VerifySignatureResult> result = new ArrayList<>();
        //查询验章文件对象

        //验章时间
        verifySignature.setVerifyTime(LocalDateTime.now());
        verifySignature.setVerifyStatus(VerifySignatureStatusEnum.VERIFY_ING.getCode());
        verifySignature.setUpdateTime(LocalDateTime.now());

        try {
            if (FileTypeEnum.PDF.getType().equals(fileType)) {
                if (!IFileUtil.isHasSignature(path)) {
                    throw new ServiceException(ResultCode.ERROR_FILE, "验章文件不存在电子签章");
                }

                //进行PDF文件验章
                result = verifyPdfSignature(verifySignature, path, cebsSdkProperties, batchGetCAOrgCertChainInfoResultDTOS);

            } else {
                //进行OFD文件验章
            }
        } catch (Exception e) {
            log.error("验章异常", e);

        }
        return result;
    }

    public static List<VerifySignatureResult> verifyPdfSignature(VerifySignature verifySignature, String pdfPath, CebsSdkProperties cebsSdkProperties, List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS) {
        PdfReader reader = null;
        try {
            //读取PDF
            reader = new PdfReader(pdfPath);
        } catch (IOException e) {
            log.error("读取PDF异常", e);
            throw new ServiceException(ResultCode.ERROR_FILE, "验签失败，读取文件异常");
        }

        //所有签名验章结果
        List<VerifySignatureResult> verifySignatureResultList = new ArrayList<>();
        try (PdfDocument pdfDoc = new PdfDocument(reader);
        ) {
            // 获取 SignatureUtil 实例
            SignatureUtil signUtil = new SignatureUtil(pdfDoc);
            //获取签名域名称集合
            List<String> signatureNames = signUtil.getSignatureNames();
            //BC的安全模式
            Security.addProvider(new BouncyCastleProvider());
            //循环获取签名域
            for (String signatureName : signatureNames) {
                //签名批次号
                String batchNumber = signatureName.contains("_") ? signatureName.substring(0, signatureName.lastIndexOf("_")) : signatureName;
                //筛选同一批次号是否已经验章
                Optional<VerifySignatureResult> signatureResultOptional = verifySignatureResultList.stream().filter(t -> t.getSignatureName().startsWith(batchNumber)).findFirst();
                if (signatureResultOptional.isPresent()) {
                    VerifySignatureResult signatureResult = signatureResultOptional.get();
                    signatureResult.setBatchSignTimes(signatureResult.getBatchSignTimes() + 1);
                    continue;
                }

                //构造验章结果对象
                VerifySignatureResult verifySignatureResult = new VerifySignatureResult();
                verifySignatureResult.setVerifySignatureId(verifySignature.getId());
                verifySignatureResult.setCreateTime(LocalDateTime.now());
                verifySignatureResult.setBatchSignTimes(1);

                PdfDictionary v = signUtil.getSignatureDictionary(signatureName);
                PdfString contents = v.getAsString(PdfName.Contents);
                // 获取签名数据
                ASN1InputStream asn1InputStream = new ASN1InputStream(contents.getValueBytes());
                ASN1Sequence seq = (ASN1Sequence) asn1InputStream.readObject();
                asn1InputStream.close();

                //签名算法OID
                String oid = ICertUtil.findSignatureOid(seq);
                //判断签名算法类型
                if (CommonConstant.OID_PKCS.equals(oid)) {
                    parsePdfPkcs7Signature(signUtil, signatureName, verifySignatureResult, batchGetCAOrgCertChainInfoResultDTOS, cebsSdkProperties);
                } else {
                    //国标解析
                    parsePdfGmtSignature(reader, v, seq, signatureName, verifySignatureResult, cebsSdkProperties, batchGetCAOrgCertChainInfoResultDTOS);
                }
                verifySignatureResultList.add(verifySignatureResult);
            }
        } catch (Exception e) {
            log.error("验章异常：", e);
            throw new ServiceException(ResultCode.ERROR_VERIFY_SIGNATURE_FAIL, ResultCode.ERROR_VERIFY_SIGNATURE_FAIL.getMessage());
        }

        //验章结果备注
        Set<String> remarkList = new HashSet<>();
        //验证结果
        AtomicBoolean verifyResult = new AtomicBoolean(true);
        List<VerifySignatureResult> result = verifySignatureResultList;
        verifySignatureResultList.stream().forEach(t -> {
            //证书有效性或者签名有效性只要有一个无效则验证结果无效
            if (!t.getCertValidity() || !t.getSignatureValidity()) {
                verifyResult.set(false);
                if (StringUtils.hasText(t.getCertValidityRemark())) {
                    remarkList.add(t.getCertValidityRemark());
                }
                if (StringUtils.hasText(t.getSignatureValidityRemark())) {
                    remarkList.add(t.getSignatureValidityRemark());
                }
                return;
            }
        });

        //验章完成时间
        verifySignature.setVerifyFinishTime(LocalDateTime.now());
        //验章结果
        verifySignature.setVerifyResult(verifyResult.get());
        verifySignature.setVerifyResultRemark(String.join(",", remarkList));
        //验章状态
        verifySignature.setVerifyStatus(VerifySignatureStatusEnum.VERIFIED.getCode());
        verifySignature.setUpdateTime(LocalDateTime.now());
//        verifySignatureRepository.updateById(verifySignature);
        //更新操作记录状态
//        updateFileOperateRecord(verifySignature.getTransactionId(), verifyResult.get() ? CommonConstant.STATUS_20 : CommonConstant.STATUS_30);
        return result;
    }

    /**
     * @param signUtil              所有签名域字段
     * @param signatureName         签名域名称
     * @param verifySignatureResult 验章结果对象
     * @Description 解析PDF签名信息
     * @Return void
     * @Exception:
     */
    private static void parsePdfPkcs7Signature(SignatureUtil signUtil,
                                               String signatureName,
                                               VerifySignatureResult verifySignatureResult,
                                               List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS
            , CebsSdkProperties cebsSdkProperties) throws Exception {
        //获取签名的pkcs7数据
        PdfPKCS7 pkcs7 = signUtil.readSignatureData(signatureName);
        //当前签名域包含的证书
        X509Certificate certificate = pkcs7.getSigningCertificate();
        //==========解析签章证书===========
        SignatureCertVO signatureCertVO = parseSignatureCert(verifySignatureResult, certificate);

        //签署时间
        LocalDateTime signTime = DateTimeUtil.toLocalDateTime(pkcs7.getSignDate().getTime());
        verifySignatureResult.setSignatureTime(signTime);
        //签章有效性
        boolean signVerify = pkcs7.verifySignatureIntegrityAndAuthenticity();
        verifySignatureResult.setSignatureValidity(signVerify);
        //e)验证签章者证书有效性 f)验证签章时间的有效性
        String certMsg = verifyCertAndSignedTime(pkcs7.getSignDate().getTime(), certificate, pkcs7.getSignCertificateChain(), cebsSdkProperties, batchGetCAOrgCertChainInfoResultDTOS);
        verifySignatureResult.setCertValidity(StringUtils.hasText(certMsg) ? false : true);
        verifySignatureResult.setCertValidityRemark(certMsg);
        verifySignatureResult.setSignatureName(signatureName);
        verifySignatureResult.setSigner(signatureCertVO.getSigner());
        verifySignatureResult.setSignReason(pkcs7.getReason());
        verifySignatureResult.setSignLocation(pkcs7.getLocation());
    }

    private static SignatureCertVO parseSignatureCert(VerifySignatureResult verifySignatureResult, X509Certificate certificate) {
        String certStr = null;
        try {
            //将签名证书转Base64字符串
            certStr = Base64Utils.encodeToString(certificate.getEncoded());
        } catch (CertificateEncodingException e) {
//            log.error("验章id：{}验章结果id：{}，签名证书转Base64字符串异常", verifySignatureResult.getVerifySignatureId(), verifySignatureResult.getId(), e);
            throw new ServiceException(ResultCode.ERROR_VERIFY_SIGNATURE_FORMAT_DATA, ResultCode.ERROR_VERIFY_SIGNATURE_FORMAT_DATA.getMessage());
        }

        //版本
        int version = certificate.getVersion();
        //证书序列号(16进制字符串)
        String certSn = certificate.getSerialNumber().toString(16);
        //签名算法
        String sigAlgName = certificate.getSigAlgName();
        //颁发者
        String issuerName = certificate.getIssuerDN().getName();
        //生效时间
        LocalDateTime certNotBefore = DateTimeUtil.toLocalDateTime(certificate.getNotBefore());
        //失效时间
        LocalDateTime certNotAfter = DateTimeUtil.toLocalDateTime(certificate.getNotAfter());
        //授权秘钥标识符
        String authKeyIdent = Hex.encodeHexString(ICertUtil.getAuthorityKeyIdentifier(certificate));
        //签章者密钥标识符
        String signerKeyIdent = Hex.encodeHexString(ICertUtil.getSubjectKeyIdentifier(certificate));
        //基本约束
        StringBuilder fundamentalConstraint = new StringBuilder();
        int basicConstraints = certificate.getBasicConstraints();
        if (basicConstraints != -1) {
            fundamentalConstraint.append("Subject Type=CA").append("\n");
            if (basicConstraints == Integer.MAX_VALUE) {
                fundamentalConstraint.append("Path Length Constraint=None");
            } else {
                fundamentalConstraint.append("Path Length Constraint=").append(basicConstraints);
            }
        } else {
            fundamentalConstraint.append("Subject Type=End Entity").append("\n Path Length Constraint=None");
        }
        //密钥用法
        String keyUsage = "不可用于数字签名";
        if (ICertUtil.isValidKeyUsage(certificate)) {
            keyUsage = "数字签名";
        }
        //证书主题
        String subject = ICertUtil.getCertAlias(certificate);
        //公钥
        String publicKey = Hex.encodeHexString(certificate.getPublicKey().getEncoded());

        //签章证书
        SignatureCertVO signatureCertVO = SignatureCertVO.builder()
                .version("V" + version)
                .certSn(certSn)
                .sigAlg(sigAlgName)
                .issuer(issuerName)
                .validityNotBefore(certNotBefore)
                .validityNotAfter(certNotAfter)
                .authKeyIdentifier(authKeyIdent)
                .signerKeyIdentifier(signerKeyIdent)
                .fundamentalConstraint(fundamentalConstraint.toString())
                .keyUsage(keyUsage)
                .signer(subject)
                .publicKey(publicKey)
                .build();

        verifySignatureResult.setSignCert(certStr);
        verifySignatureResult.setSignCertAnalysis(JSON.toJSONString(signatureCertVO, SerializerFeature.WriteMapNullValue));
        return signatureCertVO;
    }

    /**
     * e)验证签章者证书有效性
     * f)验证签章时间的有效性
     *
     * @param signedDate  签署时间
     * @param certificate 签名证书
     * @param chains      证书链
     * @return java.lang.String 证书吊销结果描述
     */
    public static String verifyCertAndSignedTime(Date signedDate, X509Certificate certificate, Certificate[] chains, CebsSdkProperties cebsSdkProperties, List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS) {
        String revokedMsg="";
        //签署时间
        LocalDateTime signTime = DateTimeUtil.toLocalDateTime(signedDate);
        //签章者证书生效时间
        LocalDateTime notBefore = DateTimeUtil.toLocalDateTime(certificate.getNotBefore());
        //签章者证书失效时间
        LocalDateTime notAfter = DateTimeUtil.toLocalDateTime(certificate.getNotAfter());
        if (signTime.compareTo(notBefore) < 0 || signTime.compareTo(notAfter) >= 0) {
            return "签名时证书未在有效期内";
        }

        //秘钥用法是否正确
        boolean keyUsage = ICertUtil.isValidKeyUsage(certificate);
        if (!keyUsage) {
            return "证书秘钥用法错误";
        }

        Collection<X509Certificate> certChains=null;
        //采用指定证书链进行验证
        if (ArrayUtils.isNotEmpty(chains) && chains.length >= 1) {
            log.info("采用指定印章中证书链链进行验证");
            certChains = Arrays.stream(chains).map(x -> (X509Certificate) x).collect(Collectors.toList());
            //验证签章结构体中证书链
            if (verifyCertChain(certificate,certChains)){
                log.info("签章结构体中证书链验证通过");
                //签名时证书是否注销
                revokedMsg = verifySignedCertRevoked(signTime, certificate);
                return revokedMsg;
            }
        }

        log.info("采用默认证书链进行验证");
        String issuerDN = certificate.getIssuerDN().getName();
        //获取证书中签发者的O项
        String issuerO = ICertUtil.convertToKeyValues(issuerDN).get("O").trim();
        log.info("证书签发者O值为：{}", issuerO);
        if (CertAlgEnum.RSA.getPkcs10SignAlg().equalsIgnoreCase(certificate.getSigAlgName())) {
        //获取RSA证书链
        certChains = getChain(cebsSdkProperties, issuerO, CertAlgEnum.RSA.getKeyAlg(), batchGetCAOrgCertChainInfoResultDTOS);
         } else if (CertAlgEnum.SM2.getPkcs10SignAlg().equalsIgnoreCase(certificate.getSigAlgName())) {
         //获取SM2证书链
         certChains = getChain(cebsSdkProperties, issuerO, CertAlgEnum.SM2.getKeyAlg(), batchGetCAOrgCertChainInfoResultDTOS);
         }


        if (CollectionUtil.isEmpty(certChains)) {
            return "无法获取证书链";
        }

        //验证证书链
        X509Certificate resCertificate = CertChainsUtil.findCACert(certificate, certChains);
        if (Objects.isNull(resCertificate)) {
            return "证书链验证失败";
        }

        //签名时证书是否注销
        revokedMsg = verifySignedCertRevoked(signTime, certificate);
        return revokedMsg;
    }

    /**
     * 验证签章结构体中证书链
     * @return
     */
    private static boolean verifyCertChain( X509Certificate certificate,Collection<X509Certificate> certChains){
        log.info("签章结构体中证书链验证");
        //验证证书链
        if (CollectionUtil.isEmpty(certChains)) {
            return false;
        }
        //验证证书链
        X509Certificate resCertificate = CertChainsUtil.findCACert(certificate, certChains);
        return !Objects.isNull(resCertificate);
    }

    /**
     * @param asn1Sequence          签名域结构对象
     * @param signatureName         签名域名称
     * @param verifySignatureResult 验章结果对象
     * @Description 解析PDF文件国标签名
     * @Return void
     * @Exception:
     */
    private static ComputerInfo parsePdfGmtSignature(PdfReader pdfReader,
                                                     PdfDictionary v,
                                                     ASN1Sequence asn1Sequence,
                                                     String signatureName,
                                                     VerifySignatureResult verifySignatureResult,
                                                     CebsSdkProperties cebsSdkProperties,
                                                     List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS
    ) throws Exception {
        ComputerInfo computerInfo =new ComputerInfo();
        //a)验证电子签章数据格式的正确性
        SES_Signature sesSignature = verifySignatureData(asn1Sequence);
        //签章信息
        TBS_Sign toSign = sesSignature.getToSign();
        //印章信息
        SESeal seSeal = toSign.getEseal();
        //扩展数据
        ExtensionDatas extDatas = toSign.getExtDatas();
        String certChainStr="";
        if (Objects.nonNull(extDatas)){
        for (ExtData extData : extDatas){
            if (extData.getExtnID().toString().equalsIgnoreCase("1.2.840.113549.1.1.1")){
                //获取硬盘机械码
                byte[] serialNumber = extData.getExtnValue().getOctets();
                computerInfo.setHardDiskSn(new String(serialNumber, StandardCharsets.UTF_8).replace("\"", ""));
            }else if (extData.getExtnID().toString().equalsIgnoreCase("1.2.840.113549.1.1.2")){
                //获取MAC地址
                byte[] macAddress =  extData.getExtnValue().getOctets();
                computerInfo.setMacAddress(new String(macAddress, StandardCharsets.UTF_8).replace("\"", ""));
            } else if (extData.getExtnID().toString().equalsIgnoreCase("1.2.840.113549.1.1.3")) {
                //获取CPU序列号
                byte[] cupSn =  extData.getExtnValue().getOctets();
                computerInfo.setCpuSn(new String(cupSn, StandardCharsets.UTF_8).replace("\"", ""));
            } else if (extData.getExtnID().toString().equalsIgnoreCase("1.2.840.113549.1.1.4")) {
                //获取IP地址
                byte[] ipAddress =  extData.getExtnValue().getOctets();
                computerInfo.setIpAddress(new String(ipAddress, StandardCharsets.UTF_8).replace("\"", ""));
            }else if (extData.getExtnID().toString().equalsIgnoreCase("1.2.840.113549.1.1.5")){
                //读取证书链
                byte[] certChain = extData.getExtnValue().getOctets();
                certChainStr = new String(certChain, StandardCharsets.UTF_8).replace("\"", "");
            }
        }}

        //签章者证书
        X509Certificate signerCert = IFCAUtil.readX509Certificate(sesSignature.getCert().getOctets());
        //b)验证电子签章签名值是否正确
        String msg = verifySignedValue(toSign.getEncoded("DER"), sesSignature.getSignatureAlgID(), signerCert, sesSignature.getSignature().getOctets());
//        if (!StringUtils.hasText(msg)) {
//            //组合验证电子印章(c)验证签章者证书与电子印章的匹配性、d)验证电子印章的有效性)
//            msg = assemblyVerifySeal(seSeal.getEncoded("DER"), sesSignature.getCert().getOctets(), sesSignature.getSignatureAlgID());
//        }
        if (!StringUtils.hasText(msg)) {
            //g)验证PDF原文杂凑
            msg = verifyPdfDataHash(pdfReader, v, toSign.getDataHash().getOctets(), sesSignature.getSignatureAlgID());
        }
        verifySignatureResult.setSignatureValidityRemark(msg);
        verifySignatureResult.setSignatureValidity(StringUtils.hasText(msg) ? false : true);
        //获取证书链 转换对象
        Collection<X509Certificate> x509Certificates = CertChainsUtil.convertBase64StringToCertificates(certChainStr);
        Certificate[] certificates=null;
        if (!CollectionUtil.isEmpty(x509Certificates)){
            log.info("证书链转换方法成功");
            //转换为数组方法
             certificates = x509Certificates.stream().toArray(Certificate[]::new);
        }
        //e)验证签章者证书有效性 f)验证签章时间的有效性
        String certMsg = verifyCertAndSignedTime(toSign.getTimeInfo().getDate(), signerCert, certificates , cebsSdkProperties, batchGetCAOrgCertChainInfoResultDTOS);
        verifySignatureResult.setCertValidity(StringUtils.hasText(certMsg) ? false : true);
        verifySignatureResult.setCertValidityRemark(certMsg);
        //签署时间
        LocalDateTime signTime = DateTimeUtil.toLocalDateTime(sesSignature.getToSign().getTimeInfo().getDate());
        verifySignatureResult.setSignatureTime(signTime);

        //解析证书信息填充验章证书对象
        SignatureCertVO signatureCertVO = parseSignatureCert(verifySignatureResult, signerCert);

        //印章信息
        SES_SealInfo sealInfo = seSeal.geteSealInfo();
        //印章头信息
        SES_Header sesHeader = sealInfo.getHeader();
        //印章属性信息
        SES_ESPropertyInfo sesEsPropertyInfo = sealInfo.getProperty();
        //印章图片信息
        SES_ESPictrueInfo sesEsPictrueInfo = sealInfo.getPicture();

        //解析印章
        SignatureSealVO.SignatureSealVOBuilder<?, ?> signatureSealVOBuilder = SignatureSealVO.builder()
                .version(sesHeader.getVersion().toString())
                .vId(sesHeader.getVid().toString())
                .esId(sealInfo.getEsID().toString())
                .type(sesEsPropertyInfo.getType().toString())
                .name(sesEsPropertyInfo.getName().toString())
                .certListType(sesEsPropertyInfo.getCertListType().intValueExact())
                .createDate(DateTimeUtil.toLocalDateTime(sesEsPropertyInfo.getCreateDate().getDate()))
                .validStart(DateTimeUtil.toLocalDateTime(sesEsPropertyInfo.getValidStart().getDate()))
                .validEnd(DateTimeUtil.toLocalDateTime(sesEsPropertyInfo.getValidEnd().getDate()))
                .imgType(sesEsPictrueInfo.getType().toString())
                .imgWidth(sesEsPictrueInfo.getWidth().toString())
                .imgHeight(sesEsPictrueInfo.getHeight().toString());
        ASN1Integer certListType = sesEsPropertyInfo.getCertListType();
        if (SES_ESPropertyInfo.CertListType.equals(certListType)) {
            List<String> certSnList = new ArrayList<>();
            for (ASN1OctetString certString : sesEsPropertyInfo.getCertList().getCerts()) {
                X509Certificate cert = IFCAUtil.readX509Certificate(certString.getOctets());
                certSnList.add(Hex.encodeHexString(cert.getSerialNumber().toByteArray()));
            }
            signatureSealVOBuilder.certSnList(certSnList);
        } else {
            List<String> certHashList = new ArrayList<>();
            for (CertDigestObj digestObj : sesEsPropertyInfo.getCertList().getCertDigestList()) {
                certHashList.add(Hex.encodeHexString(digestObj.getValue().getOctets()));
            }
            signatureSealVOBuilder.certHashList(certHashList);
        }
        SignatureSealVO signatureSealVO = signatureSealVOBuilder.build();

        //签章者
        verifySignatureResult.setSigner(signatureCertVO.getSigner());
        //签名域标识
        verifySignatureResult.setSignatureName(signatureName);
        //印章结构体(调试发现印章结构体可能会很大，需要longtext类型存储，所以不在进行存储)
        //verifySignatureResult.setSealStructure(Base64Utils.encodeToString(seSeal.getEncoded("DER")));
        verifySignatureResult.setSealAnalysis(JSON.toJSONString(signatureSealVO, SerializerFeature.WriteMapNullValue));
        verifySignatureResult.setSignLocation("");
        verifySignatureResult.setSignReason("");
        return computerInfo;
    }

    /**
     * a)验证电子签章数据格式的正确性
     *
     * @param asn1Sequence
     * @return 验证结果描述
     */
    public static SES_Signature verifySignatureData(ASN1Sequence asn1Sequence) {
        try {
            SES_Signature sesSignature = SES_Signature.getInstance(asn1Sequence.getEncoded("DER"));
            return sesSignature;
        } catch (IOException e) {
//            log.error("【国标电子验章】验证电子签章数据格式异常", e);
            throw new ServiceException(ResultCode.ERROR_VERIFY_SIGNATURE_FORMAT_DATA, ResultCode.ERROR_VERIFY_SIGNATURE_FORMAT_DATA.getMessage());
        }
    }

    /**
     * @param caCode            CA机构标识
     * @param signAlg           签名算法
     * @param cebsSdkProperties 初始化参数
     * @return java.util.Collection<java.security.cert.X509Certificate>
     * @description 获取证书链
     * @exception:
     */
    private static Collection<X509Certificate> getChain(CebsSdkProperties cebsSdkProperties, String caCode, String signAlg, List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS) {
        log.info("当前证书加密类型"+signAlg);
        if (signAlg.equals(EncryptionAlgorithmConstants.ALGORITHM_SM2)){
            signAlg="00";
        }else if (signAlg.equals(EncryptionAlgorithmConstants.ALGORITHM_RSA)){
            signAlg="01";
        }
        if (batchGetCAOrgCertChainInfoResultDTOS.isEmpty()) {
            log.error("获取证书链失败");
            return CertChainsUtil.convertBase64StringToCertificates("");
        } else {
            log.info("获取证书链列表成功");
            //遍历证书链集合
            for (BatchGetCAOrgCertChainInfoResultDTO batchGetCAOrgCertChainInfoResultDTO : batchGetCAOrgCertChainInfoResultDTOS) {
                log.info("开始寻找对应证书链");
//                log.info("当前印章O值是：" + caCode+"\n"+"当前证书链O值是"+batchGetCAOrgCertChainInfoResultDTO.getCaOrgCertChainCode()+"\n"+"当前印章签名算法是"+signAlg+"\n"+"当前证书链签名算法是"+batchGetCAOrgCertChainInfoResultDTO.getPublicKeyAlgorithm());
                //判断证书链标识是否匹配
                if (caCode.equals(batchGetCAOrgCertChainInfoResultDTO.getCaOrgCertChainCode().trim())&&signAlg.equals(batchGetCAOrgCertChainInfoResultDTO.getPublicKeyAlgorithm())) {
                    //证书链去除换行
                    String certificateChain = batchGetCAOrgCertChainInfoResultDTO.getCertificateChain().replace("\n", "");
                    log.info("证书链标识匹配成功 返回证书链");
                    //返回证书信息
                    return CertChainsUtil.convertBase64StringToCertificates(certificateChain);
                }

            }
            //返回空
            return CertChainsUtil.convertBase64StringToCertificates("");
        }

    }

    private static String verifySignedCertRevoked(LocalDateTime signTime, X509Certificate certificate) {
        //CRL分发点
        List<String> urlAddressList = new ArrayList<>();
        try {
            //获取证书主体信息
            TBSCertificate tbs = TBSCertificate.getInstance(certificate.getTBSCertificate());
            //证书扩展对象
            Extensions extensions = tbs.getExtensions();
            //X.509 证书的 CRL 分发点扩展,包含已吊销证书列表的 URL 或其他信息
            CRLDistPoint crlDistPoints = CRLDistPoint.fromExtensions(extensions);
            if (Objects.nonNull(crlDistPoints)) {
                // 从 CRLDistPoint 对象中获取所有分发点（DistributionPoint）
                DistributionPoint[] crlDistPointsArray = crlDistPoints.getDistributionPoints();
                // 遍历每个分发点
                for (int i = 0; i < crlDistPointsArray.length; i++) {
                    // 获取当前分发点的名称
                    DistributionPointName distributionPointName = crlDistPointsArray[i].getDistributionPoint();
                    // 获取 ASN1 编码对象，该对象包含了分发点的详细信息
                    ASN1Encodable asn1Encodable = distributionPointName.getName();
                    // 将 ASN1 编码对象转换为 GeneralNames 对象，GeneralNames 是一个包含多个 GeneralName 的集合
                    GeneralNames generalNames = GeneralNames.getInstance(asn1Encodable.toASN1Primitive().getEncoded());
                    // 获取所有 GeneralName 对象，这些对象表示不同类型的名称（如 DNS 名称、目录名称等）
                    GeneralName[] generalName = generalNames.getNames();
                    // 遍历每个 GeneralName 对象
                    for (int q = 0; q < generalName.length; q++) {
                        // 表示一个 IA5 字符串（ASCII 字符串）
                        ASN1Primitive asn1Primitive = generalName[q].getName().toASN1Primitive();
                        // 判断是否为 DERIA5String 类型
                        if (asn1Primitive instanceof DERIA5String) {
                            // 将 DERIA5String 对象转换为字符串
                            DERIA5String derIA5String = (DERIA5String) asn1Primitive;
                            // 检查字符串是否以 "http" 开头，如果是，则认为它是一个 HTTP URL 地址
                            if (derIA5String.getString().startsWith("http")) {
                                // 将 HTTP URL 地址添加到 urlAddressList 列表中
                                urlAddressList.add(derIA5String.getString());
                            }

                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取证书CRL(吊销证书列表)下载地址异常", e);
        }

        if (CollectionUtils.isEmpty(urlAddressList)) {
            log.error("未获取到CRL(吊销证书列表)下载地址");
            return "无法验证证书吊销状态";
        }

        //吊销描述
        String revokedMsg = null;
        for (String crl : urlAddressList) {
            X509CRL x509crl = null;
            try {
                // 创建一个 GET 请求对象，并设置超时时间为 60000 毫秒（60 秒）
                HttpRequest httpRequest = HttpUtil.createGet(crl).timeout(60000);
                // 异步执行请求并获取响应体
                String http_proxy = System.getenv("http_proxy");
                if (Objects.nonNull(http_proxy)) {
                    URL proxyUrl = new URL(http_proxy);
                    httpRequest.setHttpProxy(proxyUrl.getHost(), proxyUrl.getPort());
                }
                InputStream inStream = httpRequest.executeAsync().bodyStream();
                // 生成 X509CRL 对象，用于表示证书吊销列表（CRL）
                x509crl = CertChainsUtil.generateCRL(inStream);
            } catch (Exception e) {
                // 捕获生成 CRL 时的异常，并记录错误日志，然后继续处理下一个 CRL
                log.error("获取证书CRL({})内容异常", crl, e);
                revokedMsg = "CRL分发点未能成功验证证书是否注销";
                continue;
            }

            //获取与给定证书对应的吊销条目（如果存在），以检查该证书是否已被吊销
            X509CRLEntry revokedCert = x509crl.getRevokedCertificate(certificate);
            // 如果没有找到对应的吊销条目，则继续处理下一个 CRL
            if (Objects.isNull(revokedCert)) {
                revokedMsg = null;
                continue;
            }

            // 检查吊销日期是否早于或等于签署时间，如果是，则记录日志并返回 "签名时签名证书已吊销"
            if (DateTimeUtil.toLocalDateTime(revokedCert.getRevocationDate()).compareTo(signTime) < 1) {
                log.error("CRL({})查询结果，签名时证书已吊销", crl);
                revokedMsg = "签名时证书处于吊销状态";
            }
        }
        return revokedMsg;
    }

    /**
     * b)验证电子签章签名值是否正确
     *
     * @param signVal        签名原值
     * @param signedVal      签名值
     * @param signerCert     签章者签名证书
     * @param signatureAlgID 签名算法
     * @return 验证结果描述
     */
    public static String verifySignedValue(byte[] signVal, ASN1ObjectIdentifier signatureAlgID, X509Certificate signerCert, byte[] signedVal) {
        //签章有效性
        boolean signVerify = false;
        try {
            Signature sg = Signature.getInstance(signatureAlgID.getId(), new BouncyCastleProvider());
            sg.initVerify(signerCert);
            sg.update(signVal);
            signVerify = sg.verify(signedVal);
        } catch (Exception e) {
            log.error("【国标电子验章】验证电子签章签名值异常", e);
            if (e instanceof NoSuchAlgorithmException) {
                return "电子签章签名值无效(签名算法无效)";
            } else if (e instanceof InvalidKeyException) {
                return "电子签章签名值无效(密钥无效)";
            }
        }
        if (!signVerify) {
            return "电子签章签名值无效";
        }
        return null;
    }

    /**
     * 组合验证电子印章
     * c)验证签章者证书与电子印章的匹配性
     * d)验证电子印章的有效性
     *
     * @param sealByte       电子印章
     * @param signerCertByte 签章者证书
     * @param signatureAlgID 签名算法标识
     * @return 验证结果描述
     */
    public static String assemblyVerifySeal(byte[] sealByte, byte[] signerCertByte, ASN1ObjectIdentifier signatureAlgID) {
        //d)验证电子印章的有效性
        String msg = verifySESeal(sealByte);
        if (StringUtils.hasText(msg)) {
            return msg;
        }
        SESeal seSeal = SESeal.getInstance(sealByte);
        //c)验证签章者证书与电子印章的匹配性
        return verifyCertMatching(signerCertByte, signatureAlgID, seSeal);
    }

    /**
     * g)验证PDF原文杂凑
     *
     * @param pdfReader     PDF阅读器
     * @param pdfDictionary PDF字典
     * @param dataHash      签章信息中的原文杂凑
     * @return 验证结果描述
     */
    public static String verifyPdfDataHash(PdfReader pdfReader, PdfDictionary pdfDictionary, byte[] dataHash, ASN1ObjectIdentifier signatureAlgID) {
        try {
            //签名原文输出流
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            //读取文件内容
            PdfArray b = pdfDictionary.getAsArray(PdfName.ByteRange);
            RandomAccessFileOrArray rf = pdfReader.getSafeFile();
            byte[] readBuf = new byte[8192];
            for (int k = 0; k < b.size(); ++k) {
                int start = b.getAsNumber(k).intValue();
                int length = b.getAsNumber(++k).intValue();

                rf.seek(start);
                while (length > 0) {
                    int rd = rf.read(readBuf, 0, Math.min(length, readBuf.length));
                    if (rd <= 0) {
                        break;
                    }
                    length -= rd;
                    output.write(readBuf, 0, rd);
                }
            }
            //原文数据
            byte[] srcData = output.toByteArray();
            //算法枚举
            AlgorithmEnum algorithmEnum = AlgorithmEnum.getAlgEnum(signatureAlgID);
            //原文摘要
            byte[] digestHash = GBTSignatureUtil.buildSignDataDigest(srcData, algorithmEnum);
            //比对原文摘要
            boolean oriDigestVerify = Arrays.equals(digestHash, dataHash);
            if (!oriDigestVerify) {
                log.error("【国标电子验章】电子签章原文摘要比对结果：{}", false);
                return "文档已被修改或损坏(电子签章原文摘要比对失败)";
            }
        } catch (Exception e) {
            log.error("【国标电子验章】电子签章原文摘要比对异常：", e);
            return "文档已被修改或损坏(电子签章原文摘要比对失败)";
        }
        return null;
    }

    /**
     * d)验证电子印章的有效性
     *
     * @param sealByte 电子印章
     * @return 验证结果描述
     */
    public static String verifySESeal(byte[] sealByte) {
        try {
            //a)验证电子印章数据格式的正确性
            SESeal seSeal = SESeal.getInstance(sealByte);
            //b)验证电子印章签名值是否正确
            //制章者证书
            X509Certificate makerCert = IFCAUtil.readX509Certificate(seSeal.getCert().getOctets());
            Signature signature = Signature.getInstance(seSeal.getSignAlgID().toString(), new BouncyCastleProvider());
            signature.initVerify(makerCert);
            signature.update(seSeal.geteSealInfo().getEncoded("DER"));
            //验证电子印章中的签名
            boolean signVerify = signature.verify(seSeal.getSignedValue().getBytes());
            if (!signVerify) {
                log.error("【国标电子验章】电子印章签名验证结果：false，电子印章签名无效");
                return "电子印章签名无效";
            }
            //c)验证电子印章制章者证书有效性
            //d)验证电子印章的有效期
            SES_ESPropertyInfo propertyInfo = seSeal.geteSealInfo().getProperty();
            LocalDateTime validStart = DateTimeUtil.toLocalDateTime(propertyInfo.getValidStart().getDate());
            LocalDateTime validEnd = DateTimeUtil.toLocalDateTime(propertyInfo.getValidEnd().getDate());
            LocalDateTime nowTime = LocalDateTime.now();
            if (validStart.compareTo(nowTime) > 0 || validEnd.compareTo(nowTime) < 1) {
                log.error("【国标电子验章】电子印章有效期{} - {}，印章已失效", validStart.format(DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS)), validEnd.format(DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS)));
                return "电子印章已失效";
            }
        } catch (Exception e) {
            log.error("【国标电子验章】验证电子印章异常", e);
            if (e instanceof NoSuchAlgorithmException) {
                return "电子印章无效(签名算法无效)";
            } else if (e instanceof InvalidKeyException) {
                return "电子印章无效(秘钥无效)";
            }
            return "电子印章无效";
        }
        return null;
    }

    /**
     * c)验证签章者证书与电子印章的匹配性
     *
     * @param signerCert     签章者签名证书
     * @param signatureAlgID 签名算法标识
     * @param seSeal         电子印章
     * @return 验证结果描述
     */
    public static String verifyCertMatching(byte[] signerCert, ASN1ObjectIdentifier signatureAlgID, SESeal seSeal) {
        //电子印章中签章者证书类型
        ASN1Integer certListType = seSeal.geteSealInfo().getProperty().getCertListType();
        //电子印章中签章者证书列表
        CertInfoList certInfoList = seSeal.geteSealInfo().getProperty().getCertList().getCerts();
        //电子印章中签章者证书杂凑列表
        CertDigestList certDigestList = seSeal.geteSealInfo().getProperty().getCertList().getCertDigestList();

        //c)验证签章者证书与电子印章的匹配性
        boolean certMatching = false;
        //1 - 数字证书类型
        if (SES_ESPropertyInfo.CertListType.equals(certListType)) {
            for (ASN1OctetString asn1OctetString : certInfoList) {
                //进行证书二进制比对
                certMatching = Arrays.equals(signerCert, asn1OctetString.getOctets());
                if (certMatching) {
                    break;
                }
            }
        } else {
            for (CertDigestObj certDigestObj : certDigestList) {
                //签章者证书杂凑值
                byte[] certHash = GBTSignatureUtil.buildSignDataDigest(signerCert, AlgorithmEnum.getAlgEnum(signatureAlgID));
                //进行证书杂凑比对
                certMatching = Arrays.equals(certHash, certDigestObj.getValue().getOctets());
                if (certMatching) {
                    break;
                }
            }
        }
        if (!certMatching) {
            return "签章者证书与电子印章不匹配";
        }
        return null;
    }

    /**
     * @param getSignatureInfoDTO 获取签章信息参数
     * @Description 获取签章信息
     * @Return com.cebpubservice.signature.verifyElectronicSealSignature.application.vo.GetOneVerifyResultVO
     * @Exception:
     */
    public static GetOneVerifyResultVO getSignatureInfo(GetSignatureInfoDTO getSignatureInfoDTO) {
        //检查文件地址是否存在
        String path = getSignatureInfoDTO.getPath();
        //签名域标识
        String signatureDomainId = getSignatureInfoDTO.getSignatureDomainId();
        //检查文件是否存在 返回文件类型
        String fileType = checkIfPdfExists(path);
        //本地文件路径
        String fileAbsolutePath = path;
        //验章结果对象
        VerifySignatureResult signatureResult = null;
        if (FileTypeEnum.PDF.getType().equals(fileType)) {
            //进行PDF文件验章
            signatureResult = getPdfSignatureInfo(fileAbsolutePath, getSignatureInfoDTO.getSignatureDomainId(), CertChainsUtil.readAndConvert(getSignatureInfoDTO.getCertChainPath()), getSignatureInfoDTO.getCebsSdkProperties());
        } else {
            //进行OFD文件验章
        }

        return GetOneVerifyResultVO.convert(signatureResult);
    }

    /**
     * @param  getSignatureListInfoDTO 获取指定签章信息参数
     * @Description 获取签章信息
     * @Return com.cebpubservice.signature.verifyElectronicSealSignature.application.vo.GetOneVerifyResultVO
     * @Exception:
     */
    public static List<GetOneVerifyResultVO> getSignaturesInfo(GetSignatureListInfoDTO getSignatureListInfoDTO) {
        //检查文件地址是否存在
        String path = getSignatureListInfoDTO.getPath();
        //签名域标识
        List<String> signatureDomainIds = getSignatureListInfoDTO.getSignatureDomainIds();
        //检查文件是否存在 返回文件类型
        String fileType = checkIfPdfExists(path);
        //本地文件路径
        String fileAbsolutePath = path;
        //验章结果对象
        List<VerifySignatureResult> signatureResult = null;
        if (FileTypeEnum.PDF.getType().equals(fileType)) {
            //进行PDF文件验章
            signatureResult = getPdfSignaturesInfo(fileAbsolutePath, getSignatureListInfoDTO.getSignatureDomainIds(), CertChainsUtil.readAndConvert(getSignatureListInfoDTO.getCertChainPath()), getSignatureListInfoDTO.getCebsSdkProperties());
        } else {
            //进行OFD文件验章
        }
        List<GetOneVerifyResultVO>resultVOList=new ArrayList<>();
        for (int i = 0; i <signatureResult.size() ; i++) {
            resultVOList.add(GetOneVerifyResultVO.convert(signatureResult.get(i))) ;
        }

        return resultVOList;
    }


    /**
     * @param pdfPath       PDF文件路径
     * @param signatureName 签名域名称
     * @param pdfPath       PDF文件路径
     * @param signatureName 签名域名称
     * @Description 获取PDF文件签章信息
     * @Return com.cebpubservice.signature.verifyElectronicSealSign
     * @Description 获取PDF文件签章信息
     * @Return com.cebpubservice.signature.verifyElectronicSealSignature.application.vo.VerifySealVO
     * @Exception:
     */
    private static VerifySignatureResult getPdfSignatureInfo(String pdfPath, String signatureName, List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS, CebsSdkProperties cebsSdkProperties) {
        PdfReader reader = null;
        try {
            reader = new PdfReader(pdfPath);
        } catch (IOException e) {
            log.error("读取PDF异常", e);
            throw new ServiceException(ResultCode.ERROR_FILE, "获取签章失败，读取文件异常");
        }

        //BC的安全模式
        Security.addProvider(new BouncyCastleProvider());
        try (PdfDocument pdfDoc = new PdfDocument(reader);) {
            // 获取 SignatureUtil 实例
            SignatureUtil signUtil = new SignatureUtil(pdfDoc);
            //获取签名域名称集合
            List<String> signatureNames = signUtil.getSignatureNames();
            if (!signatureNames.contains(signatureName)) {
                throw new ServiceException(ResultCode.ERROR_FILE, "未包含指定签名域");
            }

            //获取签名域
            PdfDictionary v = signUtil.getSignatureDictionary(signatureName);
            PdfString contents = v.getAsString(PdfName.Contents);
            // 获取签名数据
            ASN1InputStream asn1InputStream = new ASN1InputStream(contents.getValueBytes());
            ASN1Sequence seq = (ASN1Sequence) asn1InputStream.readObject();
            asn1InputStream.close();

            //构造验章结果对象
            VerifySignatureResult verifySignatureResult = new VerifySignatureResult();

            //签名算法OID
            String oid = ICertUtil.findSignatureOid(seq);
            //系统信息
            ComputerInfo computerInfo =new ComputerInfo();
            //判断签名算法类型
            if (CommonConstant.OID_PKCS.equals(oid)) {
                parsePdfPkcs7Signature(signUtil, signatureName, verifySignatureResult,batchGetCAOrgCertChainInfoResultDTOS,cebsSdkProperties);
            } else {
                //国标解析
                computerInfo = parsePdfGmtSignature(reader, v, seq, signatureName, verifySignatureResult, cebsSdkProperties, batchGetCAOrgCertChainInfoResultDTOS);
            }
           //插入系统信息
            verifySignatureResult.setComputerInfo(computerInfo);
            return verifySignatureResult;
        } catch (Exception e) {
            log.error("获取签章异常", e);
            throw new ServiceException(ResultCode.ERROR_FILE, "获取签章失败" + e.getMessage());
        }
    }



    /**
     * @param pdfPath       PDF文件路径
     * @param pdfPath       PDF文件路径
     * @Description 获取PDF文件签章信息
     * @Return com.cebpubservice.signature.verifyElectronicSealSign
     * @Description 获取PDF文件签章信息
     * @Return com.cebpubservice.signature.verifyElectronicSealSignature.application.vo.VerifySealVO
     * @Exception:
     */
    private static List<VerifySignatureResult> getPdfSignaturesInfo(String pdfPath, List<String> signatureNames, List<BatchGetCAOrgCertChainInfoResultDTO> batchGetCAOrgCertChainInfoResultDTOS, CebsSdkProperties cebsSdkProperties) {
        PdfReader reader = null;
        try {
            reader = new PdfReader(pdfPath);
        } catch (IOException e) {
            log.error("读取PDF异常", e);
            throw new ServiceException(ResultCode.ERROR_FILE, "获取签章失败，读取文件异常");
        }
        List<VerifySignatureResult>resultList=new ArrayList<>();
        //BC的安全模式
        Security.addProvider(new BouncyCastleProvider());
        try (PdfDocument pdfDoc = new PdfDocument(reader);) {
            // 获取 SignatureUtil 实例
            SignatureUtil signUtil = new SignatureUtil(pdfDoc);
            for (int i = 0; i <signatureNames.size() ; i++) {
                //获取签名域名称集合
                List<String> signatureName = signUtil.getSignatureNames();
                if (!signatureNames.contains(signatureNames.get(i))) {
                    throw new ServiceException(ResultCode.ERROR_FILE, "未包含指定签名域");
                }

                //获取签名域
                PdfDictionary v = signUtil.getSignatureDictionary(signatureName.get(i));
                PdfString contents = v.getAsString(PdfName.Contents);
                // 获取签名数据
                ASN1InputStream asn1InputStream = new ASN1InputStream(contents.getValueBytes());
                ASN1Sequence seq = (ASN1Sequence) asn1InputStream.readObject();
                asn1InputStream.close();

                //构造验章结果对象
                VerifySignatureResult verifySignatureResult = new VerifySignatureResult();

                //签名算法OID
                String oid = ICertUtil.findSignatureOid(seq);
                //系统信息
                ComputerInfo computerInfo =new ComputerInfo();
                //判断签名算法类型
                if (CommonConstant.OID_PKCS.equals(oid)) {
                    parsePdfPkcs7Signature(signUtil, signatureName.get(i), verifySignatureResult,batchGetCAOrgCertChainInfoResultDTOS,cebsSdkProperties);
                } else {
                    //国标解析
                    computerInfo = parsePdfGmtSignature(reader, v, seq, signatureName.get(i), verifySignatureResult, cebsSdkProperties, batchGetCAOrgCertChainInfoResultDTOS);
                }
                //插入系统信息
                verifySignatureResult.setComputerInfo(computerInfo);
                resultList.add(verifySignatureResult);

            }
            return resultList;
        } catch (Exception e) {
            log.error("获取签章异常", e);
            throw new ServiceException(ResultCode.ERROR_FILE, "获取签章失败" + e.getMessage());
        }
    }


    /**
     * @description 获取文件验章列表
     */
    public static List<GetFileElectronicSealSignatureListVO> getFileElectronicSealSignatureList(GetFileElectronicSealSignatureListDTO getFileElectronicSealSignatureListDTO) {

        List<GetFileElectronicSealSignatureListVO> getFileElectronicSealSignatureListVOS = new ArrayList<>();
        //验证文件是否存在
        String fileType = checkIfPdfExists(getFileElectronicSealSignatureListDTO.getPath());


        //判断文件是PDF文件
        if (FileTypeEnum.PDF.getType().equals(fileType)) {
            //验证PDF文件是否可用
            IFileUtil.verifyPdfUsable(getFileElectronicSealSignatureListDTO.getPath());
            if (!IFileUtil.isHasSignature(getFileElectronicSealSignatureListDTO.getPath())) {
                throw new ServiceException(ResultCode.ERROR_FILE, "验章文件不存在电子签章");

            }
        } else {
            //验证OFD文件是否可用
            return getFileElectronicSealSignatureListVOS;
        }
        try(PdfReader pdfReader = new PdfReader(getFileElectronicSealSignatureListDTO.getPath())) {
            PdfDocument pdfDocument = new PdfDocument(pdfReader);
            SignatureUtil signUtil = new SignatureUtil(pdfDocument);
            PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, false);

            // 获取所有的表单字段
            Map<String, PdfFormField> fields = form.getFormFields();
            List<String> signatureNames = signUtil.getSignatureNames();
            for (String name : signatureNames) {
                try {
                    // 获取签名信息
                    com.itextpdf.signatures.PdfSignature signature = signUtil.getSignature(name);

                    // 获取证书信息
                    X509Certificate certificate = getCertificate(signUtil, name);
                    if (Objects.isNull(certificate)) {
                        log.error("验章失败，签名域：" + name + "，证书信息获取失败");
                        continue;
                    }
                    String signer = ICertUtil.getCertAlias(certificate);

                    // 解析签名时间
                    LocalDateTime signatureTime = DateTimeUtil.convertPdfDateToLocalDateTime(signature.getDate().toString());

                    // 获取签名域所在的页面编号
                    PdfFormField field = fields.get(name);
                    int pageNumber = pdfDocument.getPageNumber(field.getWidgets().get(0).getPage());

                    // 构建签名列表对象
                    GetFileElectronicSealSignatureListVO vo = GetFileElectronicSealSignatureListVO.builder()
                            .signatureDomainId(name)
                            .signatureTime(signatureTime)
                            .signer(signer)
                            .page(pageNumber)
                            .build();

                    getFileElectronicSealSignatureListVOS.add(vo);

                    // 记录日志
                    log.info("签名域:{}, 签名时间:{}, 签名人:{}, 签名页码:{}", name, signatureTime, signer, pageNumber);
                } catch (PdfException e) {
                    // 记录详细的异常信息
                    log.error("签名域:{}, 解析异常: {}", name, e.getMessage(), e);
                    continue;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //对getFileElectronicSealSignatureListVOS根据page进行排序
        getFileElectronicSealSignatureListVOS.sort(Comparator.comparingInt(GetFileElectronicSealSignatureListVO::getPage));
        return getFileElectronicSealSignatureListVOS;
    }

    protected static X509Certificate getCertificate(SignatureUtil signUtil, String signatureName) {
        X509Certificate cert = null;
        try {
            PdfDictionary v = signUtil.getSignatureDictionary(signatureName);
            PdfString contents = v.getAsString(PdfName.Contents);
            // 获取签名数据
            ASN1InputStream asn1InputStream = new ASN1InputStream(contents.getValueBytes());
            ASN1Sequence seq = (ASN1Sequence) asn1InputStream.readObject();
            asn1InputStream.close();

            //签名算法OID
            String oid = ICertUtil.findSignatureOid(seq);
            //判断签名算法类型
            if (CommonConstant.OID_PKCS.equals(oid)) {
                //获取签名的pkcs7数据
                PdfPKCS7 pkcs7 = signUtil.readSignatureData(signatureName);
                //当前签名域包含的证书
                cert = pkcs7.getSigningCertificate();
            } else {
                //国标解析
                SES_Signature sesSignature = verifySignatureData(seq);
                //签章信息
                TBS_Sign toSign = sesSignature.getToSign();
                //印章信息
                SESeal seSeal = toSign.getEseal();
                //签章者证书
                cert = IFCAUtil.readX509Certificate(sesSignature.getCert().getOctets());
            }

        } catch (Exception e) {
            log.error("验章失败，签名域：" + signatureName + "，证书信息获取失败", e);
            return null;
        }
        return cert;
    }


}